// 该组件为通用 Markdown 编辑器组件，被多个页面复用，已归类到 common 目录
<script setup lang="ts">
  import { MdEditor, ToolbarNames } from 'md-editor-v3'
  import 'md-editor-v3/lib/style.css'
  import { computed, onMounted, PropType, reactive, ref } from 'vue'
  import { ElMessage, FormRules } from 'element-plus'
  import { Plus } from '@element-plus/icons-vue'
  import { saveOrUpdate } from '@/api/blog.ts'
  import TagSelect from '@/components/common/TagSelect.vue'
  import { tree } from '@/api/category.ts'
  import { upload } from '@/api/file.ts'
  import { Blog, BlogSaveOrUpdateParam, Category } from '@/types'
  import { compress } from 'image-conversion'
  import { blobToFile, getImageScale } from '@/utils/file-util.ts'
  import { Mark } from '@vavt/v3-extension'
  import 'md-editor-v3/lib/style.css'

  const { data, close } = defineProps({
    data: {
      type: Object as PropType<Blog>,
      required: true,
    },
    close: {
      type: Function,
      required: true,
    },
  })

  const toolbars: ToolbarNames[] = [
    'bold',
    'underline',
    'italic',
    '-',
    'title',
    'strikeThrough',
    'sub',
    'sup',
    'quote',
    'unorderedList',
    'orderedList',
    'task',
    '-',
    'codeRow',
    'code',
    'link',
    'image',
    'table',
    'mermaid',
    'katex',
    0,
    '-',
    'revoke',
    'next',
    'save',
    '=',
    'pageFullscreen',
    'fullscreen',
    'preview',
    'previewOnly',
    'htmlPreview',
    'catalog',
  ]
  const categoryData = ref<Category[]>([])

  const rules: FormRules = {
    title: [
      {
        required: true,
        message: '请输入标题',
        trigger: 'blur',
      },
    ],
  }

  const param = reactive<BlogSaveOrUpdateParam>({
    id: '',
    title: '',
    tags: [],
    mkContent: '',
    categoryId: '',
    summary: '',
    backgroundImg: '',
  })
  const cascaderProps = ref({
    checkStrictly: true, //严格的遵守父子节点不互相关联
    label: 'name',
    value: 'id',
    emitPath: false, //返回单个值
  })

  const initParam = () => {
    param.id = data.id
    param.title = data.title
    param.mkContent = data.mkContent
    param.categoryId = data.categoryId
    param.tags = data?.tags?.map(item => item.name) ?? []
    param.summary = data?.summary
    param.backgroundImg = data?.backgroundImg || ''
  }
  const onSubmit = async () => {
    await onSave()
    close()
  }

  const onSave = async () => {
    let data = await saveOrUpdate(param)
    ElMessage.success('保存成功')
    //保存id
    if (!param.id) {
      param.id = data.id
    }
  }
  const onUploadImg = async (files: File[], callback: (_urls: string[]) => void) => {
    //压缩图片
    const compressImages = files.map(item => {
      return new Promise<File>((resolve, _reject) => {
        ;(async () => {
          const scale = await getImageScale(1024, item)
          const res = await compress(item, { quality: 0.8, scale })
          resolve(blobToFile(res, item.name))
        })()
      })
    })
    const compressFiles = await Promise.all(compressImages)
    //上传图片
    const data = await upload(compressFiles, 1)
    callback(data.map(item => item.url))
  }

  // 背景图相关
  const backgroundImgUrl = computed(() => {
    if (param.backgroundImg) {
      return `/api/file/${param.backgroundImg}`
    }
    return ''
  })

  const beforeBackgroundUpload = (file: File) => {
    const isImage = file.type.indexOf('image/') === 0
    const isLt5M = file.size / 1024 / 1024 < 5

    if (!isImage) {
      ElMessage.error('只能上传图片文件!')
      return false
    }
    if (!isLt5M) {
      ElMessage.error('图片大小不能超过 5MB!')
      return false
    }
    return true
  }

  const handleBackgroundUpload = async (options: { file: File }) => {
    const { file } = options

    try {
      // 压缩图片
      const scale = await getImageScale(1920, file)
      const compressedFile = await compress(file, { quality: 0.8, scale })
      const finalFile = blobToFile(compressedFile, file.name)

      // 上传
      const data = await upload([finalFile], 1)
      if (data && data.length > 0) {
        param.backgroundImg = data[0].id
        ElMessage.success('背景图上传成功')
      }
    } catch (error) {
      ElMessage.error('背景图上传失败')
      console.error('Upload error:', error)
    }
  }

  const removeBackground = () => {
    param.backgroundImg = ''
    ElMessage.success('背景图已移除')
  }

  const getCategory = async () => {
    categoryData.value = await tree({})
  }

  const summaryLoading = ref(false)

  const onGenerateSummary = async () => {
    if (!param.mkContent || param.mkContent.length < 10) {
      ElMessage.warning('请先输入足够的正文内容')
      return
    }
    summaryLoading.value = true
    param.summary = '' // 清空原有摘要
    try {
      const response = await fetch('/api/ai/chat', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Accept: 'text/event-stream',
        },
        body: JSON.stringify({
          messages: [
            {
              role: 'system',
              content:
                '你是一个专业的博客内容助手，请根据用户输入的正文内容，提炼出一段简明扼要、通顺流畅的中文摘要，字数控制在50字以内。',
            },
            { role: 'user', content: param.mkContent },
          ],
        }),
      })
      if (!response.body) throw new Error('无流式响应')
      const reader = response.body.getReader()
      const decoder = new TextDecoder('utf-8')
      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        const chunk = decoder.decode(value, { stream: true })
        // 兼容SSE格式，按行分割
        chunk.split('"\\n\\n"').forEach(line => {
          if (line.startsWith('"data:"')) {
            const content = line
              .replace('"data:"', '')
              .replace(/\\ndata:/g, '\n')
              .replace(/"/g, '')
            if (content) param.summary += content
          }
        })
      }
      ElMessage.success('AI摘要生成成功')
    } catch (e) {
      ElMessage.error('AI摘要生成失败，请稍后重试')
      console.error(e)
    } finally {
      summaryLoading.value = false
    }
  }

  getCategory()
  onMounted(initParam)
</script>

<template>
  <el-form ref="form" :model="param" :rules="rules">
    <el-row :gutter="20">
      <el-col :span="22">
        <el-form-item label="标题：" prop="title" label-position="left">
          <el-input v-model="param.title" type="text" placeholder="" />
        </el-form-item>
      </el-col>
    </el-row>
    <el-row>
      <el-col :span="10">
        <el-form-item label="标签：" prop="tag" label-position="left">
          <TagSelect v-model="param.tags" />
        </el-form-item>
      </el-col>
      <el-col :span="2"></el-col>
      <el-col :span="10">
        <el-form-item label="分类：" prop="tag" label-position="left">
          <el-cascader
            v-model="param.categoryId"
            style="width: 100%"
            :options="categoryData"
            :props="cascaderProps"
            clearable
          />
        </el-form-item>
      </el-col>
    </el-row>

    <el-form-item label="摘要：" prop="summary" label-position="left">
      <el-input v-model="param.summary" type="textarea" placeholder="" />
      <el-button type="primary" :loading="summaryLoading" @click="onGenerateSummary">
        生成摘要
      </el-button>
      <div v-if="summaryLoading" style="color: #409eff; margin-top: 6px">
        AI正在生成摘要，请稍候...
      </div>
    </el-form-item>

    <el-form-item label="背景图：" prop="backgroundImg" label-position="left">
      <el-upload
        class="background-uploader"
        :show-file-list="false"
        :before-upload="beforeBackgroundUpload"
        :http-request="handleBackgroundUpload"
      >
        <img v-if="backgroundImgUrl" :src="backgroundImgUrl" class="background-img" />
        <el-icon v-else class="background-uploader-icon">
          <Plus />
        </el-icon>
      </el-upload>
      <el-button
        v-if="param.backgroundImg"
        type="danger"
        size="small"
        style="margin-left: 10px"
        @click="removeBackground"
      >
        移除
      </el-button>
    </el-form-item>

    <!--  markdown编辑器  -->
    <el-form-item prop="content" label-position="top">
      <MdEditor
        v-model="param.mkContent"
        :on-save="onSave"
        :on-upload-img="onUploadImg"
        :toolbars="toolbars"
        preview-theme="github"
        :toolbars-exclude="['github']"
        no-iconfont
      >
        <!--suppress VueUnrecognizedSlot -->
        <template #defToolbars>
          <Mark>
            <!--suppress VueUnrecognizedSlot -->
            <template #trigger>M</template>
          </Mark>
        </template>
      </MdEditor>
    </el-form-item>
    <!--  markdown编辑器  -->
    <el-form-item>
      <el-button type="primary" @click="onSubmit">保存</el-button>
    </el-form-item>
  </el-form>
</template>

<style scoped>
  .background-uploader {
    display: inline-block;
  }

  .background-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
  }

  .background-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
  }

  .background-img {
    width: 200px;
    height: 120px;
    display: block;
    object-fit: cover;
  }

  .el-icon.background-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 200px;
    height: 120px;
    text-align: center;
    line-height: 120px;
  }
</style>
